/**
 * Created by Administrator on 2017/1/10.
 */

var Player = require('./player').Player;

// 玩家管理器
function PlayerManager() {
    this.openids = {}; // openid->uid的映射
    this.uids = {}; // uid->openid的映射
    this.players = {}; // 玩家数据缓存
    this.tickCount = 0;
    this.onlineCount = 0;
}

PlayerManager.prototype = {

    // 初始化
    init: function (callback) {
        // 加载平台数据
        var cursor = DB.plat.find();
        cursor.each(function (err, item) {
            if (err) {
                callback && callback(err);
                return;
            }

            if (item) {
                this.openids[item._id] = +item.uid;
                this.uids[+item.uid] = item._id;
            }

            if (cursor.isClosed()) {
                callback && callback();
            }
        }.bind(this));
    },

    // 注册一个新平台帐号
    addPlat: function (openid, callback) {
        var uid = this.openids[openid];
        if (uid) {
            callback(null, uid);
            return;
        }

        DB.plat.findOneAndUpdate({_id: '_userid'}, {$inc: {'ai': 1}}, {'returnOriginal': false}, function (err, result) {
            if (err) {
                callback(err);
                return;
            }

            if (!result.value) {
                callback(Code.DB_ERROR);
                return;
            }

            var newUID = +(result.value.ai);
            DB.plat.insertOne({_id: openid, uid: newUID, time: Date.getStamp()}, function (err, result) {
                if (err) {
                    callback(err);
                } else {
                    this.openids[openid] = newUID;
                    this.uids[newUID] = openid;
                    callback(null, newUID);
                }
                ;
            }.bind(this));
        }.bind(this));
    },

    // 获取玩家数据
    getPlayer: function (uid, callback) {
        uid = +uid;
        if (this.players.hasOwnProperty(uid)) {
            callback(this.players[uid]);
        } else {
            this.loadPlayer(uid, function (player) {
                callback(player);
            }.bind(this));
        }
    },

    // 加载玩家数据
    loadPlayer: function (uid, callback) {
        var openid = this.getOpenid(uid);
        if (!openid) {
            callback && callback();
            return;
        }

        var player = new Player(uid);
        player.openid = openid;

        player.init({}, function (suss) {
            if (suss) {
                this.players[uid] = player;
                callback && callback(player);
            } else {
                callback && callback();
            }
        }.bind(this));
    },

    // 保存所有数据
    saveAll: function (force, callback) {
        var players = this.players;
        async.each(Object.keys(players), function (uid, cb) {
            var player = players[uid];
            if (!player) {
                cb();
                return;
            }

            player.save(force, function (err) {
                cb();
            });
        }, function (err) {
            callback && callback(err);
        });
    },

    getOpenid: function (uid) {
        return this.uids[uid];
    },

    getUid: function (openID) {
        return this.openids[openID];
    },

    tick: function () {
        this.tickCount++;
        var nowStamp = Date.getStamp();

        var onlineCount = 0;
        ExObject.each(this.players, function (uid, player) {
            if (player.isOnline()) {
                onlineCount++;
            }
        });
        this.onlineCount = onlineCount;

        if (this.tickCount % 300 == 0) {
            var timeoutIdArray = [];
            ExObject.each(this.players, function (uid, player) {
                var marks = player.user.marks;
                if (player.isRobot()) {
                    if (nowStamp > (marks.loginTime + 3600)) {
                        timeoutIdArray.push(uid);
                    }
                } else {
                    if (marks.logoutTime > marks.loginTime && nowStamp > (marks.logoutTime + 600)) {
                        timeoutIdArray.push(uid);
                        player.save(true);
                    }
                }
            });

            timeoutIdArray.forEach(function (uid) {
                delete this.players[uid];
            }.bind(this));
        }

        if (this.tickCount % 600 == 199) {
            DB.stat.save({
                total: this.getOpenidCount(),
                online: this.onlineCount,
                t: nowStamp
            });
        }
    },

    getOpenidCount: function () {
        return Object.keys(this.openids).length;
    },

    getOnlineCount: function () {
        return this.onlineCount + 1;
    },

    getVirtualOnlineCount: function () {
        var onlineCount = this.getOnlineCount();

        var vCount = onlineCount * 10 + ExNumber.rand(10);
        if (onlineCount >= 100) {
            vCount += 5000;
        }
        return vCount;

        var virtualSetting = gGlobalManager.getConfig("virtualSetting");
        if (!virtualSetting) {
            return vCount;
        }

        var onlineCountLimit = virtualSetting["onlineCountLimit"] || 500;
        var onlineCountRate = virtualSetting["onlineCountRate"] || 5;
        var onlineCountMin = virtualSetting["onlineCountMin"] || 100;

        var rateLimit = Math.floor(onlineCountLimit / onlineCountRate);
        if (onlineCount > rateLimit) {
            return onlineCountLimit + onlineCount;
        } else {
            if (onlineCount < Math.floor(rateLimit / onlineCountRate)) {
                var newRate = Math.round(onlineCountRate * onlineCountRate / 2);
                return onlineCountMin + onlineCount * newRate + ExNumber.rand(newRate);
            } else {
                return onlineCountMin + onlineCount * onlineCountRate + ExNumber.rand(onlineCountRate);
            }
        }
    },
    getInviter: function (inviterUid, callback) {
        inviterUid = +inviterUid;

        var result = [];
        DB.user.find({"invite.inviter": inviterUid}).toArray(function (err, items) {
            if (err) {
                callback(err);
            }

            result = items || [];
            callback(null,result);
        });
    },
};

exports.PlayerManager = PlayerManager;